package backend

import (
	"context"
	"dockerview/backend/models"
	"github.com/docker/docker/client"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/sirupsen/logrus"
	"github.com/wailsapp/wails/v2/pkg/runtime"
	"io"
	"os"
)

// App struct
type App struct {
	ctx     context.Context
	Version string
	log     *logrus.Logger
	DB      *gorm.DB
	docker  *client.Client

	paths struct {
		HomeDir      string
		DAGDir       string
		TMPDir       string
		EncryptedDir string
		EmptyTXFile  string
		PrevTXFile   string
		LastTXFile   string
		AddressFile  string
		//ImageDir     string
	}
	UserLoggedIn bool
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{}
}

// Startup is called at application startup
func (a *App) Startup(ctx context.Context) {
	var err error
	// Perform your setup here
	a.ctx = ctx
	a.log = logrus.New()
	err = a.initDirectoryStructure()
	if err != nil {
		a.log.Errorln("Unable to set up directory structure. Reason: ", err)
	}
	a.initLogger()
	a.UserLoggedIn = false
	a.Version = VERSION
	a.docker = a.InitDocker()
	a.DB, err = gorm.Open("sqlite3", a.paths.DAGDir+"/store.db")
	if err != nil {
		a.log.Panicln("failed to connect database", err)
	}
	// Migrate the schema
	a.DB.AutoMigrate(&models.Dockerview{},&models.Endpoint{})
}

// DomReady is called after the front-end dom has been loaded
func (a App) DomReady(ctx context.Context) {
	// Add your action here
}

// Shutdown is called at application termination
func (a *App) Shutdown(ctx context.Context) {
	// Perform your teardown here
}

// Initializes the Directory Structure and stores the paths to the WalletApplication struct.
func (a *App) initDirectoryStructure() error {
	//user, err := user.Current()
	home, err := os.Getwd()
	a.log.Info("HomeDir: ", home)
	if err != nil {
		return err
	}

	a.paths.HomeDir = home                            // Home directory of the user
	a.paths.DAGDir = a.paths.HomeDir + "/.dockerview" // DAG directory for configuration files and wallet specific data
	a.paths.TMPDir = a.paths.DAGDir + "/tmp"
	a.paths.LastTXFile = a.paths.TMPDir + "/last_tx"
	a.paths.PrevTXFile = a.paths.TMPDir + "/prev_tx"
	a.paths.EmptyTXFile = a.paths.TMPDir + "/genesis_tx"
	//a.paths.ImageDir = "./frontend/src/assets/img/" // Image Folder

	a.log.Info("DAG Directory: ", a.paths.DAGDir)

	err = a.directoryCreator(a.paths.DAGDir, a.paths.TMPDir)
	if err != nil {
		return err
	}

	return nil
}

// initLogger writes logs to STDOUT and a.paths.DAGDir/wallet.log
func (a *App) initLogger() {
	logFile, err := os.OpenFile(a.paths.DAGDir+"/dockerview.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
	if err != nil {
		a.log.Fatal("Unable to create log file.")
	}
	mw := io.MultiWriter(os.Stdout, logFile)
	a.log.SetOutput(mw)
	a.log.SetFormatter(&logrus.TextFormatter{
		ForceColors:   true,
		FullTimestamp: true,
	})
}

func (a *App) sendSuccess(msg string) {

	if len(msg) > 200 {
		msg = msg[:200] // Restrict error size for frontend
		runtime.EventsEmit(a.ctx, "success", msg)
		return
	}
	runtime.EventsEmit(a.ctx, "success", msg)
}

func (a *App) sendWarning(msg string) {

	if len(msg) > 200 {
		msg = msg[:200] // Restrict error size for frontend
		runtime.EventsEmit(a.ctx, "warning", msg)
		return
	}
	runtime.EventsEmit(a.ctx, "warning", msg)
}

func (a *App) sendError(msg string, err error) {
	var errStr string
	if err != nil {
		b := []byte(err.Error())
		if len(b) > 80 {
			errStr = string(b[:80]) // Restrict error size for frontend
		} else if len(b) < 80 {
			errStr = string(b)
		} else {
			errStr = ""
		}

		runtime.EventsEmit(a.ctx, "error_handling", msg, errStr+" ...")
	} else {
		runtime.EventsEmit(a.ctx, "error_handling", msg, errStr+" ...")
	}

}
